package net.jlibrary.common.project.config;

import java.util.List;
import java.util.Properties;

import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.logicalcobwebs.proxool.ProxoolDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.stereotype.Repository;

import com.alibaba.druid.filter.logging.Slf4jLogFilter;
import com.alibaba.druid.pool.DruidDataSource;

import net.jlibrary.common.core.dao.ValidateSignInterceptor;
import net.jlibrary.common.core.dao.XProxoolDataSource;
import net.jlibrary.common.tools.StringUtil;

/**
 * 载入数据库配置
 * @author sunlf
 *
 */
@Configuration
@PropertySource("classpath:/config.properties")
//@ComponentScan(basePackages = { "net.jlibrary.common.purview","net.jlibrary.common.project.listener"})
@ComponentScan(basePackages = { "net.jlibrary.**.dao" }, includeFilters = { @Filter(value = {Repository.class }) })
public class SpringDataSourceConfig {
	private final Log log = LogFactory.getLog(getClass());
	@Resource
    private Environment env;
	
//	@Bean(destroyMethod="close")
//	public ProxoolDataSource dataSource() {
//		ProxoolDataSource dataSource = new XProxoolDataSource();
//		dataSource.setAlias(env.getRequiredProperty("datasource.alias"));
//		dataSource.setDriver(env.getRequiredProperty("datasource.driverClassName"));
//		dataSource.setDriverUrl(env.getRequiredProperty("datasource.dataBaseUrl"));
//		dataSource.setUser(env.getRequiredProperty("datasource.dataBaseName"));
//		dataSource.setPassword(env.getRequiredProperty("datasource.dataBasePassword"));
//		dataSource.setHouseKeepingSleepTime(env.getRequiredProperty("proxool.house.keeping.sleep.time" ,Long.class));
//		dataSource.setPrototypeCount(env.getRequiredProperty("proxool.prototype.count" ,Integer.class));
//		dataSource.setMinimumConnectionCount(env.getRequiredProperty("proxool.minimum.connection.count" ,Integer.class));
//		dataSource.setMaximumConnectionCount(env.getRequiredProperty("proxool.maximum.connection.count" ,Integer.class));
//		dataSource.setSimultaneousBuildThrottle(env.getRequiredProperty("proxool.simultaneous.build.throttle" ,Integer.class));
//		dataSource.setMaximumActiveTime(env.getRequiredProperty("proxool.maximum.active.time" ,Long.class));
//		dataSource.setTrace(env.getRequiredProperty("proxool.trace" ,Boolean.class));
//		dataSource.setHouseKeepingTestSql(env.getRequiredProperty("proxool.house.keeping.test.sql"));
//		dataSource.setTestBeforeUse(true);
//		return dataSource;
//	}
	
	@Bean(destroyMethod="close")
	public DruidDataSource dataSourceDruid() {
		DruidDataSource dataSource = new DruidDataSource();
		dataSource.setName(env.getRequiredProperty("datasource.alias"));
		dataSource.setUrl(env.getRequiredProperty("datasource.dataBaseUrl"));
		dataSource.setUsername(env.getRequiredProperty("datasource.dataBaseName"));
		dataSource.setPassword(env.getRequiredProperty("datasource.dataBasePassword"));
		
		
		dataSource.setInitialSize(env.getRequiredProperty("druid.initialSize",Integer.class));
		dataSource.setMinIdle(env.getRequiredProperty("druid.minIdle",Integer.class));
		dataSource.setMaxActive(env.getRequiredProperty("druid.maxActive",Integer.class));
		dataSource.setMaxWait(env.getRequiredProperty("druid.maxWait",Integer.class));
		dataSource.setPoolPreparedStatements(env.getRequiredProperty("druid.poolPreparedStatements",Boolean.class));
		dataSource.setMaxOpenPreparedStatements(env.getRequiredProperty("druid.maxOpenPreparedStatements",Integer.class));
		dataSource.setValidationQuery(env.getRequiredProperty("druid.validationQuery"));
		dataSource.setTestOnBorrow(env.getRequiredProperty("druid.testOnBorrow",Boolean.class));
		dataSource.setTestOnReturn(env.getRequiredProperty("druid.testOnReturn",Boolean.class));
		dataSource.setTestWhileIdle(env.getRequiredProperty("druid.testWhileIdle",Boolean.class));
		dataSource.setTimeBetweenEvictionRunsMillis(env.getRequiredProperty("druid.timeBetweenEvictionRunsMillis",Long.class));
		dataSource.setMinEvictableIdleTimeMillis(env.getRequiredProperty("druid.minEvictableIdleTimeMillis",Long.class));
		
		dataSource.setRemoveAbandoned(env.getRequiredProperty("druid.removeAbandoned",Boolean.class));
		dataSource.setRemoveAbandonedTimeout(env.getRequiredProperty("druid.removeAbandonedTimeout",Integer.class));
		dataSource.setLogAbandoned(env.getRequiredProperty("druid.logAbandoned",Boolean.class));
		try {
			dataSource.setFilters(env.getRequiredProperty("druid.filters"));
		} catch (Exception e) {
			log.error("setFilters is error", e);
		}
		return dataSource;
	}
	
	@Bean
	public Slf4jLogFilter logFilter() {
		Slf4jLogFilter slf4jLogFilter = new Slf4jLogFilter();
		slf4jLogFilter.setStatementExecutableSqlLogEnable(false);
		return slf4jLogFilter;
	}
	/*
	@Bean(destroyMethod="close")
	public XBasicDataSource dataSource() {
		XBasicDataSource dataSource = new XBasicDataSource();
		dataSource.setUsername(env.getRequiredProperty("datasource.dataBaseName"));
		dataSource.setPassword(env.getRequiredProperty("datasource.dataBasePassword"));
		dataSource.setUrl(env.getRequiredProperty("datasource.dataBaseUrl"));
		dataSource.setDriverClassName(env.getRequiredProperty("datasource.driverClassName"));
		
		//验证相关
		dataSource.setValidationQuery(env.getRequiredProperty("dbcp.validationquery"));
		dataSource.setValidationQueryTimeout(env.getRequiredProperty("dbcp.validationquerytimeout", Integer.class));
		dataSource.setTestWhileIdle(env.getRequiredProperty("dbcp.testwhileIdle", Boolean.class));
		
		//连接数相关
		dataSource.setMaxActive(env.getRequiredProperty("dbcp.maxactive", Integer.class));
		dataSource.setMaxIdle(env.getRequiredProperty("dbcp.maxidle", Integer.class));
		dataSource.setMinIdle(env.getRequiredProperty("dbcp.minidle", Integer.class));
		dataSource.setMaxWait(env.getRequiredProperty("dbcp.maxwait", Long.class));
		
		return dataSource;
	}*/
	
	@Bean
	public LocalSessionFactoryBean sessionFactory() {
		LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
		sessionFactory.setDataSource(dataSourceDruid());
		Properties properties = new Properties();
		properties.setProperty("hibernate.dialect", env.getRequiredProperty("hibernate.dialect"));
		properties.setProperty("hibernate.show_sql", env.getRequiredProperty("hibernate.show_sql"));
		properties.setProperty("hibernate.cache.provider_class", env.getRequiredProperty("hibernate.cache.provider_class"));
		properties.setProperty("hibernate.cache.use_query_cache", env.getRequiredProperty("hibernate.cache.use_query_cache"));
		properties.setProperty("hibernate.cache.region.factory_class", env.getRequiredProperty("hibernate.cache.region.factory_class"));
		properties.setProperty("hibernate.query.substitutions", env.getRequiredProperty("hibernate.query.substitutions"));
		properties.setProperty("hibernate.hbm2ddl.auto", env.getRequiredProperty("hibernate.hbm2ddl.auto"));
		properties.setProperty("hibernate.jdbc.batch_size", env.getRequiredProperty("hibernate.jdbc.batch_size"));
		properties.setProperty("hibernate.jdbc.fetch_size", env.getRequiredProperty("hibernate.jdbc.fetch_size"));
		sessionFactory.setHibernateProperties(properties);
		
		//设置拦截器
		sessionFactory.setEntityInterceptor(new ValidateSignInterceptor());
		
		//设置实体
		String sdomain = env.getRequiredProperty("project.domain.packages");
		if(StringUtil.isNotBlank(sdomain)) {
			log.debug("=======================>");
			sessionFactory.setPackagesToScan("net.jlibrary.**.domain",sdomain);
		} else {
			sessionFactory.setPackagesToScan("net.jlibrary.**.domain");
		}
		
		return sessionFactory;
	}
	
//	public Set<String> domainClassName() {
//		Set<String> ds = new HashSet<String>();
//		ds.add("net.jlibrary.**.domain");
//		return ds;
//	}
	
	@Bean
	public HibernateTransactionManager txManager() {
		HibernateTransactionManager transactionManager = new HibernateTransactionManager();
		transactionManager.setSessionFactory(sessionFactory().getObject());
		return transactionManager;
	}
	
//	@Bean
//	public IDao dao() {
//		DefaultHibernateDao dao = new DefaultHibernateDao();
//		dao.setSessionFactory(sessionFactory().getObject());
//		dao.setCacheQueries(true);
//		return dao;
//	}
}
